package com.qqtech.qquan.user.service;

import java.math.BigDecimal;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.qqtech.core.common.constant.CoreConst;
import com.qqtech.core.common.enums.YesNoEnum;
import com.qqtech.core.common.exception.PayException;
import com.qqtech.core.common.util.ArithUtil;
import com.qqtech.core.common.util.StringUtil;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.order.enums.OrderPayWayDictEnum;
import com.qqtech.qquan.order.model.OrderPayLog;
import com.qqtech.qquan.order.service.OrderHandleService;
import com.qqtech.qquan.user.dao.UserMoneyLogDao;
import com.qqtech.qquan.user.enums.UserMoneyLogTypeDictEnum;
import com.qqtech.qquan.user.enums.UserValueOsTypeDictEnum;
import com.qqtech.qquan.user.enums.UserWithdrawStatusDictEnum;
import com.qqtech.qquan.user.model.UserMoneyLog;
import com.qqtech.qquan.user.model.UserMoneyLogQuery;
import com.qqtech.qquan.user.model.UserMoneyLogVo;
import com.qqtech.qquan.user.model.UserValue;
import com.qqtech.qquan.user.model.UserWithdraw;
import com.qqtech.qquan.user.model.UserWithdrawVo;

@Service
public class UserMoneyLogServiceImpl extends BaseServiceImpl<UserMoneyLog> implements UserMoneyLogService {
	public static final Logger log = LoggerFactory.getLogger(UserMoneyLogServiceImpl.class);
	@Resource
	private UserValueService userValueService;
	@Resource
	private UserMoneyLogDao userMoneyLogDao;
	@Resource
	private UserWithdrawService userWithdrawService;
	@Resource
	private OrderHandleService orderHandleService;

	@Override
	protected BaseDao<UserMoneyLog> getBaseDao() {
		return userMoneyLogDao;
	}

	@Override
	public double getValidMoney(Integer userId) {
		UserValue userValue = userValueService.getById(userId);
		if (userValue != null) {
			int totalInt = userValue.getMoney() == null ? 0 : userValue.getMoney();
			BigDecimal total = new BigDecimal(totalInt).divide(new BigDecimal(CoreConst.VALUE_CORE_MONEYRATE), 2,
					BigDecimal.ROUND_HALF_UP);
			UserWithdrawVo userWithdraw = new UserWithdrawVo();
			userWithdraw.setUserId(userId);
			userWithdraw.setStatus(UserWithdrawStatusDictEnum.APPLYING.getCode());
			userWithdraw.setPayingStatus(UserWithdrawStatusDictEnum.PAYING.getCode());
			List<UserWithdraw> uwList = userWithdrawService.getHandleMoney(userWithdraw);
			if (uwList != null && uwList.size() > 0) {
				for (UserWithdraw uw : uwList) {
					total = total.subtract(uw.getCash());
				}
			}
			return ArithUtil.roundMoney(total);
		}
		return 0;
	}

	@Override
	public double getValidQuan(Integer userId) {
		UserValue userValue = userValueService.getById(userId);
		if (userValue != null) {
			int totalInt = userValue.getQuanValue() == null ? 0 : userValue.getQuanValue();
			BigDecimal total = new BigDecimal(totalInt).divide(new BigDecimal(CoreConst.VALUE_CORE_MONEYRATE), 2,
					BigDecimal.ROUND_HALF_UP);
			return ArithUtil.roundMoney(total);
		}
		return 0;
	}

	@Override
	public void addMoneyToUser(Integer userId, Integer money, String remark, UserMoneyLogTypeDictEnum type) {
		if (userId == null || money == null || money.intValue() == 0) {
			return;
		}
		if (type == null) {
			type = UserMoneyLogTypeDictEnum.QUAN;
		}
		if (StringUtil.isBlank(remark)) {
			remark = "余额变更";
			if (type.equals(UserMoneyLogTypeDictEnum.QUAN)) {
				remark = "圈币变更";
			}
		}
		UserMoneyLog userMoneyLog = new UserMoneyLog();
		userMoneyLog.setMoney(money);
		userMoneyLog.setUserId(userId);
		userMoneyLog.setRemark(remark);
		userMoneyLog.setType(type.getCode());
		this.insert(userMoneyLog);
	}

	@Override
	public void payWithUserMoney(String orderNo, String buyerId, Integer payUserId, Integer payMoney, String remark) {
		if (payUserId == null || payMoney == null || payMoney.intValue() == 0) {
			return;
		}
		if (payMoney < 0) {
			payMoney = -payMoney;
		}
		if (StringUtil.isBlank(remark)) {
			remark = "余额支付";
		}
		int valid = new Double(ArithUtil.round(this.getValidMoney(payUserId) * CoreConst.VALUE_CORE_MONEYRATE, 0))
				.intValue();
		if (payMoney > valid) {
			throw new PayException("可使用余额已不足支付");
		}
		UserValue userValue = userValueService.getById(payUserId);
		if (userValue == null) {
			throw new PayException("支付数据有误");
		}
		UserMoneyLog userMoneyLog = new UserMoneyLog();
		userMoneyLog.setMoney(-payMoney);
		userMoneyLog.setUserId(payUserId);
		userMoneyLog.setRemark(remark + "(余额支付)");
		userMoneyLog.setType(UserMoneyLogTypeDictEnum.MONEY.getCode());
		this.insert(userMoneyLog);
		// 生成订单支付记录
		OrderPayLog orderPayLog = new OrderPayLog();
		orderPayLog.setOrderNo(orderNo);
		orderPayLog.setTradeNo(orderNo);
		orderPayLog.setPayUserId(payUserId);
		orderPayLog.setBuyerEmail(null);
		orderPayLog.setBuyerId(buyerId);
		orderPayLog.setValue(new BigDecimal(payMoney).divide(new BigDecimal(CoreConst.VALUE_CORE_MONEYRATE), 2,
				BigDecimal.ROUND_HALF_UP));
		orderPayLog.setPayWay(OrderPayWayDictEnum.MONEY.getCode());
		orderPayLog.setShopDiscountValue(BigDecimal.ZERO);
		orderPayLog.setShopDiscountRate(BigDecimal.ZERO);
		orderHandleService.payOrder(orderPayLog);
	}

	@Override
	public void payWithUserQuan(String orderNo, String buyerId, Integer payUserId, Integer payMoney, String remark,BigDecimal shopDiscountValue,BigDecimal shopDiscountRate) {
		if (payUserId == null || payMoney == null || payMoney.intValue() == 0) {
			return;
		}
		if (payMoney < 0) {
			payMoney = -payMoney;
		}
		if (StringUtil.isBlank(remark)) {
			remark = "圈币支付";
		}
		int valid = new Double(ArithUtil.round(this.getValidQuan(payUserId) * CoreConst.VALUE_CORE_MONEYRATE, 0))
				.intValue();
		if (payMoney > valid) {
			throw new PayException("可使用圈币已不足支付");
		}
		UserValue userValue = userValueService.getById(payUserId);
		if (userValue == null) {
			throw new PayException("支付数据有误");
		}
		UserMoneyLog userMoneyLog = new UserMoneyLog();
		userMoneyLog.setMoney(-payMoney);
		userMoneyLog.setUserId(payUserId);
		userMoneyLog.setRemark(remark + "(圈币支付)");
		userMoneyLog.setType(UserMoneyLogTypeDictEnum.QUAN.getCode());
		this.insert(userMoneyLog);
		// 生成订单支付记录
		OrderPayLog orderPayLog = new OrderPayLog();
		orderPayLog.setOrderNo(orderNo);
		orderPayLog.setTradeNo(orderNo);
		orderPayLog.setPayUserId(payUserId);
		orderPayLog.setBuyerEmail(null);
		orderPayLog.setBuyerId(buyerId);
		orderPayLog.setValue(new BigDecimal(payMoney).divide(new BigDecimal(CoreConst.VALUE_CORE_MONEYRATE), 2,
				BigDecimal.ROUND_HALF_UP));
		orderPayLog.setPayWay(OrderPayWayDictEnum.QUAN.getCode());
		orderPayLog.setShopDiscountValue(shopDiscountValue);
		orderPayLog.setShopDiscountRate(shopDiscountRate);
		orderHandleService.payOrder(orderPayLog);
	}

	/**
	 * 方法重构。新增流水记录，同时修改用户的余额或圈币
	 */
	@Override
	public int insert(UserMoneyLog entity) {
		if (entity != null && entity.getMoney() != null && entity.getMoney().intValue() != 0
				&& entity.getUserId() != null) {
			if (entity.getBalance() == null) {
				UserValue userValue = userValueService.getById(entity.getUserId());
				if (userValue != null) {
					int userLeft = (userValue.getMoney() == null ? 0 : userValue.getMoney())
							+ (userValue.getQuanValue() == null ? 0 : userValue.getQuanValue());
					entity.setBalance((entity.getMoney() == null ? 0 : entity.getMoney().intValue()) + userLeft);
					if (entity.getType() != null
							&& UserMoneyLogTypeDictEnum.QUAN.getCode() == entity.getType().intValue()) {
						userValueService.alterQuanValue(entity.getUserId(), entity.getMoney());
					} else {
						userValueService.alterMoney(entity.getUserId(), entity.getMoney());
					}
				} else {
					entity.setBalance(entity.getMoney() == null ? 0 : entity.getMoney().intValue());
					userValue = new UserValue();
					userValue.setId(entity.getUserId());
					if (entity.getType() != null
							&& UserMoneyLogTypeDictEnum.QUAN.getCode() == entity.getType().intValue()) {
						userValue.setMoney(0);
						userValue.setQuanValue(entity.getMoney() == null ? 0 : entity.getMoney().intValue());
					} else {
						userValue.setMoney(entity.getMoney() == null ? 0 : entity.getMoney().intValue());
						userValue.setQuanValue(0);
					}
					userValue.setIsBackground(YesNoEnum.NO.getCode());
					userValue.setOsType(UserValueOsTypeDictEnum.ANDROID.getCode());
					userValueService.insert(userValue);
				}
			}
			if (entity.getType() == null) {
				entity.setType(UserMoneyLogTypeDictEnum.MONEY.getCode());
			}
			userMoneyLogDao.insert(entity);
		}
		return 0;
	}

	@Override
	public int delete(UserMoneyLog entity) {
		return 0;
	}

	@Override
	public int deleteById(Integer id) {
		return 0;
	}

	@Override
	public int deleteAll() {
		return 0;
	}

	@Override
	public int updateById(UserMoneyLog entity) {
		return 0;
	}

	@Override
	public void deleteByIdInBatch(List<Integer> idList) {
		// nothing to do
	}

	@Override
	public void insertInBatch(List<UserMoneyLog> entityList) {
		for (UserMoneyLog userMoneyLog : entityList) {
			insert(userMoneyLog);
		}
	}

	@Override
	public void updateInBatch(List<UserMoneyLog> entityList) {
		// nothing to do
	}

	@Override
	public Page<UserMoneyLogVo> queryPageListAdmin(UserMoneyLogQuery query, Pageable pageable) {
		return userMoneyLogDao.queryPageListAdmin(query, pageable);
	}

	@Override
	public int queryCountAdmin(UserMoneyLogQuery query) {
		return userMoneyLogDao.queryCountAdmin(query);
	}

	@Override
	public List<UserMoneyLogVo> queryListAdmin(UserMoneyLogQuery query, Pageable pageable) {
		return userMoneyLogDao.queryListAdmin(query, pageable);
	}
}